/******************************************************************************
 * FileName:    gwin_remote_leshi.h
 * Desc:        遥控
 *                  乐式达协议
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

/*-------------------------- Includes ---------------------------------------*/
#include "gwin_board.h"
#include "gwin_remote.h"
#include "gwin_main_task.h"
#include "gwin_protocol_task.h"

/*-------------------------- Macro Definitions ------------------------------*/
#define LOCAL_DEBUG_EN                      ( 0 )
#if LOCAL_DEBUG_EN
#define GWIN_DEBUG(...)                     USER_DEBUG(__VA_ARGS__)
#else
#define GWIN_DEBUG(...)
#endif


/*-------------------------- Type Declarations ------------------------------*/
/**
 * @brief 遥控协议 偏移
 *
 *      遙控协议  Adv Data单元格式: Len + Type + Data
 *          Adv Data : 0x11 0x07 数据
 *                                  厂商ID（4Byte） + 数据长度（1Byte） + 识别码（1Byte） + 遥控id（4Byte） + 硬件类型（1Byte） + 房间号与设备号（1Byte） + 命令累加（1Byte） + 命令类型（1Byte） + 命令参数长度（1Byte） + 命令参数（6Byte） + CRC16（1Byte）
 */
typedef enum
{
    GWIN_REMOTE_PROT_INDEX_LEN,
    GWIN_REMOTE_PROT_INDEX_TYPE,
    GWIN_REMOTE_PROT_INDEX_COMPANY_1,
    GWIN_REMOTE_PROT_INDEX_COMPANY_2,
    GWIN_REMOTE_PROT_INDEX_COMPANY_3,
    GWIN_REMOTE_PROT_INDEX_COMPANY_4,
    GWIN_REMOTE_PROT_INDEX_PAYLOAD_LEN,
    GWIN_REMOTE_PROT_INDEX_ID_1,
    GWIN_REMOTE_PROT_INDEX_REMOTE_1,
    GWIN_REMOTE_PROT_INDEX_REMOTE_2,
    GWIN_REMOTE_PROT_INDEX_REMOTE_3,
    GWIN_REMOTE_PROT_INDEX_REMOTE_4,
    GWIN_REMOTE_PROT_INDEX_HW_TYPE,
    GWIN_REMOTE_PROT_INDEX_GROUP,
    GWIN_REMOTE_PROT_INDEX_INDEX,
    GWIN_REMOTE_PROT_INDEX_CMD,
    GWIN_REMOTE_PROT_INDEX_PARAM_LEN,
    GWIN_REMOTE_PROT_INDEX_DATA_0,
    GWIN_REMOTE_PROT_INDEX_MAX,
}gwin_remote_prot_index_t;
#define GWIN_REMOTE_PROT_ID_1                               0x01
#define GWIN_REMOTE_PROT_ENCRYPTED_START                    ( GWIN_REMOTE_PROT_INDEX_GROUP )    // 加密数据开始
#define GWIN_REMOTE_PROT_PAYLOAD_LEN(len)                   ((len) - 6)                         // 有效数据长度
#define GWIN_REMOTE_PROT_PARAM_LEN(len)                     ((len) - 17)                        // 参数数据长度
#define GWIN_REMOTE_PROT_ENCRYPTED_DATA_LEN(payload_len)    ((payload_len) - 1 - 1 - 4)         // 加密数据长度
#define GWIN_REMOTE_PROT_ENCRYPTED_INDEX(i)                 ( i - GWIN_REMOTE_PROT_ENCRYPTED_START) // 加密数据编号

/**
 * @brief 遥控命令 对码清码
 */
typedef enum
{
    GWIN_RB_CMD_PAIR_NONE,                                  // 无
    GWIN_RB_CMD_PAIR_ADD,                                   // 对码
    GWIN_RB_CMD_PAIR_CLEAR,                                 // 清码
    GWIN_RB_CMD_PAIR_TOGGLE,                                // 未对码的则对码，已对码的则清码
}gwin_remote_btn_cmd_pair_t;



/*-------------------------- Global Variables -------------------------------*/

/*-------------------------- Local Variables --------------------------------*/
/**
 * @brief 遙控协议头
 *          Adv Data单元格式: Len + Type + Data
 *          Adv Data1 + Adv Data2
 */
static const uint8_t remote_prot_head_1[] = { 'x', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const uint8_t remote_prot_head_2[] = { 'x', 0xFF, 0x4C, 0x00, 0x02, 0x15 };
static const uint8_t remote_prot_head_3[] = { 'x', 0xFF, 0x68, 0xF2, 0x77, 0x48 };
static const uint8_t remote_prot_head_offset = sizeof(remote_prot_head_1) - 1;


/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
/**
 * @brief 解密数据
 */
static void gwin_security_decrypted_data_leshi(uint8_t remote_id_1, const uint8_t *encrypted_data, uint8_t encrypted_data_len, uint8_t *decrypted_data)
{
    static const uint8_t key_map[] = { 0xCB, 0x6A, 0x95, 0x8D, 0xB6, 0x7B, 0x35, 0x5A, 0x6E, 0x49, 0x5C, 0x85, 0x37, 0x3C, 0xA6, 0x88, };
    uint8_t key = key_map[remote_id_1 & 0x0F];
    for (uint8_t i = 0; i < encrypted_data_len; i++)
    {
        decrypted_data[i] = encrypted_data[i] ^ key;
    }
}

/**
 * @brief 遥控 配对初始化
 */
void gwin_remote_pair_init_leshi(void)
{

}

/**
 * @brief 遥控 判断协议
 */
int8_t gwin_remote_date_check_leshi(uint8_t *data, uint16_t len, remote_pair_info_t *remote_pair_info, uint8_t *adv_payload_pos, uint8_t *cmd_index)
{
    uint8_t decrypted_data[16] = { 0x00 };
    uint8_t find_head = 0;
    uint8_t _adv_payload_pos = 0;
    adv_payload_unit_t *adv_payload_unit = NULL;
    while (_adv_payload_pos < len)
    {
        adv_payload_unit = (adv_payload_unit_t *)&data[_adv_payload_pos];
        if (adv_payload_unit->len < ADV_PAYLOAD_UNIT_LEN_MIN            // 防止不按照蓝牙格式
                || adv_payload_unit->len > ADV_PAYLOAD_UNIT_LEN_MAX)    // 防止不按照蓝牙格式
        {
            break;
        }
        if (memcmp(&remote_prot_head_1[1], ((uint8_t *)adv_payload_unit) + 1, remote_prot_head_offset) == 0
                || memcmp(&remote_prot_head_2[1], ((uint8_t *)adv_payload_unit) + 1, remote_prot_head_offset) == 0
                || memcmp(&remote_prot_head_3[1], ((uint8_t *)adv_payload_unit) + 1, remote_prot_head_offset) == 0)
        {
            find_head = 1;
            break;
        }
        _adv_payload_pos += (adv_payload_unit->len + 1);
    }
    if (!find_head)
    {
        return -1;
    }
    data = (uint8_t *)adv_payload_unit;
    len = data[GWIN_REMOTE_PROT_INDEX_LEN] + 1;

    // 有效数据长度
    uint8_t payload_len = data[GWIN_REMOTE_PROT_INDEX_PAYLOAD_LEN];
    if (payload_len != GWIN_REMOTE_PROT_PAYLOAD_LEN(len - 1))
    {
        return -2;
    }
    // 识别码1
    if (GWIN_REMOTE_PROT_ID_1 != data[GWIN_REMOTE_PROT_INDEX_ID_1])
    {
        return -3;
    }
    // 解密
    gwin_security_decrypted_data_leshi(data[GWIN_REMOTE_PROT_INDEX_REMOTE_1], &data[GWIN_REMOTE_PROT_ENCRYPTED_START], GWIN_REMOTE_PROT_ENCRYPTED_DATA_LEN(payload_len), decrypted_data);

    *adv_payload_pos = _adv_payload_pos;
    memcpy(remote_pair_info->remote_id, &data[GWIN_REMOTE_PROT_INDEX_REMOTE_1], REMOTE_ID_LEN);
    if (decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_GROUP)] > 9)
    {
        // 乐式触控屏：分组是大于9的，只能做成分组不共存的模式，单分组
        remote_pair_info->group_mode = 1;
        remote_pair_info->group_id = decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_GROUP)];
    }
    else
    {
        remote_pair_info->group_id |= (0x01 << decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_GROUP)]);
    }
    *cmd_index = decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_INDEX)];
    remote_pair_info->from_le_shi = 1;

    return 0;
}


/**
 * @brief 遥控接收数据
 */
void gwin_remote_date_proc_leshi(uint8_t *data, uint16_t len, remote_pair_info_t *remote_pair_info, uint8_t *_action, uint32_t *_param)
{
    uint8_t decrypted_data[16] = { 0x00 };
//    uint8_t cmd_id = 0;
//    uint8_t btn_id = 0;
    uint8_t action = 0;
    uint32_t param = 0;
    len = data[GWIN_REMOTE_PROT_INDEX_LEN] + 1;
    uint8_t payload_len = data[GWIN_REMOTE_PROT_INDEX_PAYLOAD_LEN];

    // 解密
    gwin_security_decrypted_data_leshi(data[GWIN_REMOTE_PROT_INDEX_REMOTE_1], &data[GWIN_REMOTE_PROT_ENCRYPTED_START], GWIN_REMOTE_PROT_ENCRYPTED_DATA_LEN(payload_len), decrypted_data);

    uint8_t data_remote_to_uart[31] = { 0x00 };
    memcpy(data_remote_to_uart, data, len < sizeof(data_remote_to_uart) ? len : sizeof(data_remote_to_uart));
    memcpy(&data_remote_to_uart[GWIN_REMOTE_PROT_ENCRYPTED_START], decrypted_data, GWIN_REMOTE_PROT_ENCRYPTED_DATA_LEN(payload_len));
    gwin_protocol_data_recv(PROTOCOL_TASK_DATA_WAY_LESHI_REMOTE, data_remote_to_uart, len);

    // 数据解析
//    cmd_id = decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_INDEX)];
//    btn_id = decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_CMD)];

    GWIN_DEBUG("%02x%02x%02x%02x : group_id = 0x%04x, cmd_id = 0x%02x, btn_id = 0x%02x",
                                    remote_pair_info->remote_id[0], remote_pair_info->remote_id[1], remote_pair_info->remote_id[2], remote_pair_info->remote_id[3], remote_pair_info->group_id, cmd_id, btn_id);
    GWIN_DEBUG("data : %02x %02x %02x", decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_DATA_0) + 0], decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_DATA_0) + 1], decrypted_data[GWIN_REMOTE_PROT_ENCRYPTED_INDEX(GWIN_REMOTE_PROT_INDEX_DATA_0) + 2]);

    if (action > 0)
    {
        *_action = action;
        *_param = param;
    }
}


/*-------------------------- END OF FILE ------------------------------------*/

